﻿Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging

Public NotInheritable Class BitmapCutter
    Public Sub New()
    End Sub
    ''' <summary>
    ''' Image Rotation
    ''' </summary>
    ''' <param name="oldImage">A <see cref="System.Drawing.Image"/> source</param>
    ''' <param name="angle">Rotate angle(only -180, -90, 90, 180,)</param>
    ''' <returns></returns>
    Public Shared Function RotateImage(oldImage As Image, angle As Single) As Bitmap
        Dim na As Single = Math.Abs(angle)
        If na <> 90 AndAlso na <> 180 Then
            Throw New ArgumentException("angle could only be -180, -90, 90, 180 degrees, but now it is " + angle.ToString() + " degrees!")
        End If

        '#region "-Unused(for any degrees)-"
        'double radius = angle * Math.PI / 180.0;
        'double cos = Math.Cos(radius);
        'double sin = Math.Sin(radius);

        'int ow = oldImage.Width;
        'int oh = oldImage.Height;
        'int nw = (int)(Math.Abs(ow * cos) + Math.Abs(oh * sin));
        'int nh = (int)(Math.Abs(ow * sin) + Math.Abs(oh * cos));
        '#end region

        Dim ow As Integer = oldImage.Width
        Dim oh As Integer = oldImage.Height
        Dim nw As Integer = ow
        Dim nh As Integer = oh
        '90/-90
        If na = 90 Then
            nw = oh
            nh = ow
        End If

        Dim bmp As New Bitmap(nw, nh)
        Using g As Graphics = Graphics.FromImage(bmp)
            g.InterpolationMode = InterpolationMode.Bilinear
            g.SmoothingMode = SmoothingMode.HighQuality

            Dim offset As New Point(CInt((nw - ow) / 2), CInt((nh - oh) / 2))
            Dim rect As New Rectangle(offset.X, offset.Y, ow, oh)
            Dim center As New Point(CInt(rect.X + rect.Width / 2), CInt(rect.Y + rect.Height / 2))
            g.TranslateTransform(center.X, center.Y)
            g.RotateTransform(angle)
            g.TranslateTransform(-center.X, -center.Y)
            g.DrawImage(oldImage, rect)
            g.ResetTransform()
            g.Save()
        End Using
        Return bmp
    End Function
    ''' <summary>
    ''' Generate the new bitmap
    ''' </summary>
    ''' <param name="oldImage">A <see cref="System.Drawing.Image"/> source</param>
    ''' <param name="cut">The </param>
    ''' <returns></returns>
    Public Shared Function GenerateBitmap(oldImage As Image, cut As Cutter) As Bitmap
        If oldImage Is Nothing Then
            Throw New ArgumentNullException("oldImage")
        End If

        Dim newBitmap As Image = New Bitmap(cut.SaveWidth, cut.SaveHeight)

        'Re-paint the oldImage
        Using g As Graphics = Graphics.FromImage(newBitmap)
            g.Clear(Color.White)
            g.InterpolationMode = InterpolationMode.High
            g.SmoothingMode = SmoothingMode.HighQuality
            g.SmoothingMode = SmoothingMode.AntiAlias
            g.CompositingQuality = CompositingQuality.HighQuality
            g.DrawImage(oldImage, New Rectangle(0, 0, cut.SaveWidth, cut.SaveHeight), New Rectangle(0, 0, cut.Width, cut.Height), GraphicsUnit.Pixel)
            g.Save()
        End Using

        Dim bmp As New Bitmap(cut.CutterWidth, cut.CutterHeight)

        Using g As Graphics = Graphics.FromImage(bmp)
            g.Clear(Color.White)
            g.InterpolationMode = InterpolationMode.High
            g.SmoothingMode = SmoothingMode.HighQuality
            g.SmoothingMode = SmoothingMode.AntiAlias
            g.CompositingQuality = CompositingQuality.HighQuality
            g.DrawImage(newBitmap, 0, 0, New Rectangle(cut.X, cut.Y, cut.CutterWidth, cut.CutterHeight), GraphicsUnit.Pixel)
            g.Save()
            newBitmap.Dispose()
        End Using
        Return bmp
    End Function
End Class



''' <summary>
''' Cutter Model
''' </summary>
Public Class Cutter

#Region "-Constructor-"

    ''' <summary>
    ''' Create a new BitmapCutter.Core.API.Cutter instance
    ''' </summary>
    Public Sub New()
        Me.New(0, 0, 0, 0, 0, 0, _
         0, 0, 0)
    End Sub
    ''' <summary>
    ''' Create a new BitmapCutter.Core.API.Cutter instance
    ''' </summary>
    Public Sub New(_Zoom As Double, _X As Integer, _Y As Integer, _CutterWidth As Integer, _CutterHeight As Integer, _Width As Integer, _
     _Height As Integer)
        Me.New(_Zoom, _X, _Y, _CutterWidth, _CutterHeight, _Width, _
         _Height, CInt(_Zoom * _Width), CInt(_Zoom * _Height))
    End Sub
    ''' <summary>
    ''' Create a new BitmapCutter.Core.API.Cutter instance
    ''' </summary>
    Public Sub New(_Zoom As Double, _X As Integer, _Y As Integer, _CutterWidth As Integer, _CutterHeight As Integer, _Width As Integer, _
     _Height As Integer, _SaveWidth As Integer, _SaveHeight As Integer)
        Me._Zoom = _Zoom
        Me._X = _X
        Me._Y = _Y
        Me._CutterHeight = _CutterHeight
        Me._CutterWidth = _CutterWidth
        Me._Width = _Width
        Me._Height = _Height
        Me._SaveWidth = _SaveWidth
        Me._SaveHeight = _SaveHeight
    End Sub
#End Region

#Region "-Properties-"

    Private _SaveWidth As Integer
    ''' <summary>
    ''' Resize bitmap(Width)
    ''' </summary>
    Public Property SaveWidth() As Integer
        Get
            Return _SaveWidth
        End Get
        Set(value As Integer)
            _SaveWidth = value
        End Set
    End Property
    Private _SaveHeight As Integer
    ''' <summary>
    ''' Resize bitmap(Height)
    ''' </summary>
    Public Property SaveHeight() As Integer
        Get
            Return _SaveHeight
        End Get
        Set(value As Integer)
            _SaveHeight = value
        End Set
    End Property
    Private _Zoom As Double
    ''' <summary>
    ''' Zoom rate
    ''' </summary>
    Public Property Zoom() As Double
        Get
            Return _Zoom
        End Get
        Set(value As Double)
            _Zoom = value
        End Set
    End Property
    Private _X As Integer
    ''' <summary>
    ''' X coordinates(from left-top corner)
    ''' </summary>
    Public Property X() As Integer
        Get
            Return _X
        End Get
        Set(value As Integer)
            _X = value
        End Set
    End Property
    Private _Y As Integer
    ''' <summary>
    ''' Y coordinates(from left-top corner)
    ''' </summary>
    Public Property Y() As Integer
        Get
            Return _Y
        End Get
        Set(value As Integer)
            _Y = value
        End Set
    End Property
    Private _CutterWidth As Integer
    ''' <summary>
    ''' Width of cutter
    ''' </summary>
    Public Property CutterWidth() As Integer
        Get
            Return _CutterWidth
        End Get
        Set(value As Integer)
            _CutterWidth = value
        End Set
    End Property
    Private _CutterHeight As Integer
    ''' <summary>
    ''' Height of cutter
    ''' </summary>
    Public Property CutterHeight() As Integer
        Get
            Return _CutterHeight
        End Get
        Set(value As Integer)
            _CutterHeight = value
        End Set
    End Property
    Private _Width As Integer
    ''' <summary>
    ''' Width of original size
    ''' </summary>
    Public Property Width() As Integer
        Get
            Return _Width
        End Get
        Set(value As Integer)
            _Width = value
        End Set
    End Property
    Private _Height As Integer
    ''' <summary>
    ''' Height of original size
    ''' </summary>
    Public Property Height() As Integer
        Get
            Return _Height
        End Get
        Set(value As Integer)
            _Height = value
        End Set
    End Property
#End Region

End Class
